#include "problema.h"

using namespace std;
         
         
   /** Constructor
   * @param Fichero donde se encuentran la Altura y Anchura del contenedor y los Rectángulos */
   Problema:: Problema (ifstream &fich) {
      int W,H;
      fich >> W;
      C = Contenedor (W);
      int numelem;
      fich >> numelem;
      int h,w;
     
     for (int i = 0; i < numelem; i++) {
         fich >> w;
         fich >>h;
         Rectangulo r = Rectangulo (w,h);
         candidatos.push_back(r);
      }
      
      fich.close();

     candidatos.sort();
     //Imprimir_lista (candidatos);
      
   }
   
   
   /** Imprime por pantalla una lista de Rectángulos
   * @param lista de RectáNgulos a imprimir. 
   * @param lista de RectáNgulos a imprimir. 
   **/
   void Problema:: Imprimir_lista (list <Rectangulo> l) {
      list <Rectangulo>::iterator it;
   }



   /**
   * Resuelve el problema
   * TODO : aquí iría lo necesario para resolver los problemas, ejemplo:
   *    generar_solución_inicial
   *    mientras_no (condicion_parada)
   *       mejorar_solucion
   *    .... etc ...
   * Hay que estudiar bien lo que hace falta para que funcione con
   * todas las heuristicas
   * */
   list <Rectangulo> Problema::resolver(int tipoHeur) {
            switch(tipoHeur) {
		  case(1): { heu = new Grasp(candidatos); break; } //GRASP
		  case(2): { heu = new MultiStart(candidatos); break; } //MultiStart
		  case(3): { heu = new Tabu(candidatos, C); break; } //Tabu
		  case(4): { heu = new VNS(candidatos); break; } //VNS
		  case(5): { heu = new Genetico(candidatos, C); break; } //Genetico
		  case(6): { heu = new PSO(candidatos, C); break; } //Optimizacion PArtículas
		  case(7): { heu = new Hormigas(candidatos, C); break; } //Hormigas
		  case(8): { heu = new Dispersa(candidatos, C); break; } //Búsqueda Dispersa
		  default: { heu = new Heuristica(candidatos); break; }
	  }
	  
	  cout << "Muestro el contorno: " << endl;
	  C.listarContorno();
	  
     timeval start;
     timeval stop;
     timeval genIni;
     timeval result;
      gettimeofday(&start,NULL);
      list<Rectangulo> sol = heu->generaInicial();
      gettimeofday(&genIni,NULL);
      timersub(&genIni,&start,&result);
      //cout << "Tiempo en generar la inicial: " << (result.tv_sec + result.tv_usec/1000000.0) << endl;
      int h = INT_MAX;
      while(!(heu->parada(h))) {
         sol = heu->mejoraSolucion();     
         h = C.calcularAltura(sol);

         //cout << "Altura total (" << heu->getIteracion() << "): " << h << endl;
      }
      gettimeofday(&stop,NULL);      
      timersub(&stop,&start,&result);
           
      cout << "Tiempo total: " << (result.tv_sec + result.tv_usec/1000000.0) << endl;
      cout << "Mejor solución: " << heu->getMejorH() <<
              " encontrada en la iteración " << (heu->getIteracion() - heu->getIteracionSinCambio() - 1) << 
              endl;
      cout << "Área vacía: " << C.calcularAreaVacia(heu->getMejorSol(),heu->getMejorH()) << endl;

      return candidatos;

   }
